/**
 * @author: Yura Knoxville
 * @version: v1.1.0
 */

(function ($) {

    'use strict';

    var initBodyCaller,
        tableGroups;

    // it only does '%s', and return '' when arguments are undefined
    var sprintf = function (str) {
        var args = arguments,
            flag = true,
            i = 1;

        str = str.replace(/%s/g, function () {
            var arg = args[i++];

            if (typeof arg === 'undefined') {
                flag = false;
                return '';
            }
            return arg;
        });
        return flag ? str : '';
    };

    /**
     *数据分组
     */
    var groupBy = function (array , f) {
        var groups = {};
        array.forEach(function(o) {
            var group = f(o);
            groups[group] = groups[group] || [];
            groups[group].push(o);
        });

        return groups;
    };

    $.extend($.fn.bootstrapTable.defaults, {
        groupBy: false,
        groupByField: '',
        groupByFormatter: function (value, row, index) {
            return '';
        },
        groupBySumField: '',//分组合计字段,字段内容为数组[["title"=>"title1","value"=>1],["title"=>"title2","value"=>2]]，其中最后一组value为前n-1组value之和
        groupByTotalField: '',//总计字段,字段内容为数组[["title"=>"title1","value"=>1],["title"=>"title2","value"=>2]]，其中最后一组value为前n-1组value之和
    });

    var BootstrapTable = $.fn.bootstrapTable.Constructor,
        _initSort = BootstrapTable.prototype.initSort,
        _initBody = BootstrapTable.prototype.initBody,
        _updateSelected = BootstrapTable.prototype.updateSelected;

    BootstrapTable.prototype.initSort = function () {
        _initSort.apply(this, Array.prototype.slice.apply(arguments));

        var that = this;
        tableGroups = [];

        if ((this.options.groupBy) && (this.options.groupByField !== '')) {

            if ((this.options.sortName != this.options.groupByField)) {
                this.data.sort(function(a, b) {
                    return a[that.options.groupByField].localeCompare(b[that.options.groupByField]);
                });
            }

            var that = this;
            var groups = groupBy(that.data, function (item) {
                return [item[that.options.groupByField],item[that.options.groupBySumField],item[that.options.groupByTotalField]];
            });

            var index = 0;
            $.each(groups, function(key, value) {
                var arr = key.split(',');
                tableGroups.push({
                    id: index,
                    name: arr[0],
                    data: value,
                    sum: arr[1],
                    total: arr[2],
                });

                value.forEach(function(item) {
                    if (!item._data) {
                        item._data = {};
                    }

                    item._data['parent-index'] = index;
                });

                index++;
            });
        }
    }

    BootstrapTable.prototype.initBody = function () {
        initBodyCaller = true;

        _initBody.apply(this, Array.prototype.slice.apply(arguments));

        if ((this.options.groupBy) && (this.options.groupByField !== '')) {
            var that = this,
                checkBox = false,
                visibleColumns = 0;

            this.columns.forEach(function(column) {
                if (column.visible) {
                    visibleColumns += 1;
                }
                if (column.checkbox) {
                    checkBox = true;
                    visibleColumns -= 1;
                }
            });

            if (this.options.detailView && !this.options.cardView) {
                visibleColumns += 1;
            }
            tableGroups.forEach(function(item,index){
                var html = [];

                html.push(sprintf('<tr class="info groupBy expanded" data-group-index="%s">', item.id));

                if (that.options.detailView && !that.options.cardView) {
                    html.push('<td class="detail"></td>');
                }

                if (checkBox) {
                    html.push('<td class="bs-checkbox">',
                        '<input name="btSelectGroup" type="checkbox" />',
                        '</td>'
                    );
                }
                var formattedValue = item.name;
                if (typeof(that.options.groupByFormatter) == "function") {
                    formattedValue = that.options.groupByFormatter(item.name, item.data[0], item.id);
                }
                html.push('<td',
                    sprintf(' colspan="%s"', visibleColumns),
                    '>', formattedValue, '</td>',
                );

                html.push('</tr>');

                that.$body.find('tr[data-parent-index='+item.id+']:first').before($(html.join('')));
                html = [
                    '<tr data-parent-index="'+item.id+'">',
                    '<td colspan="'+visibleColumns+1+'" style="text-align:right">',
                    '%s',
                    '</td>',
                    '</tr>'
                ];

                if(that.options.groupBySumField != "") {
                    var n = 0, i = 0;
                    var sumField = item.data[0][that.options.groupBySumField];
                    if(sumField.length>1){
                        n = sumField.length-1;
                        //输出前n项
                        for(i=0;i<n;i++){
                            that.$body.find('tr[data-parent-index=' + item.id + ']:last').after($(sprintf(html.join(''), sumField[i]["title"]+":"+sumField[i]["value"])));
                        }
                        var strFreight = "(含上述"+ n +"项费用)";
                    }else{
                        var strFreight = "(不含运费)";
                    }
                    //输出第n项
                    that.$body.find('tr[data-parent-index=' + item.id + ']:last').after($(sprintf(html.join(''), sumField[n]["title"] + strFreight + ":￥" + sumField[n]["value"])));

                }

                //最后一次循环，添加汇总行
                if(index == tableGroups.length-1){
                    var html = [
                        '<tr class="info groupBy expanded">',
                        '<td colspan="'+visibleColumns+1+'" style="text-align:right">',
                        '%s',
                        '</td>',
                        '</tr>'
                    ];
                    if(that.options.groupByTotalField != "") {
                        var n = 0, i = 0;;
                        var totalField = item.data[0][that.options.groupByTotalField];
                        if(totalField.length>1){
                            n = totalField.length-1;
                            for(i=0;i<n;i++){
                                that.$body.find('tr:last').after($(sprintf(html.join(''),totalField[i]["title"]+":"+totalField[i]["value"])));
                            }
                            var strFreight = "(含上述"+ n +"项单列费用)";
                        }else{
                            var strFreight = "(不含运费)";
                        }
                        that.$body.find('tr:last').after($(sprintf(html.join(''), totalField[n]["title"] + strFreight + ":￥" + totalField[n]["value"])));

                    }
                }
            });
            //折叠分组子项
            this.$selectGroup = [];
            this.$body.find('[name="btSelectGroup"]').each(function() {
                var self = $(this);

                that.$selectGroup.push({
                    group: self,
                    item: that.$selectItem.filter(function () {
                        //return ($(this).closest('tr').data('parent-index') ===
                        //self.closest('tr').data('group-index'));
                    })
                });
            });
            //展开分组子项
            this.$container.off('click', '.groupBy')
                .on('click', '.groupBy', function() {
                    //$(this).toggleClass('expanded');
                    //that.$body.find('tr[data-parent-index='+$(this).closest('tr').data('group-index')+']').toggleClass('hidden');
                });

            this.$container.off('click', '[name="btSelectGroup"]')
                .on('click', '[name="btSelectGroup"]', function (event) {
                    event.stopImmediatePropagation();

                    var self = $(this);
                    var checked = self.prop('checked');
                    that[checked ? 'checkGroup' : 'uncheckGroup']($(this).closest('tr').data('group-index'));
                });
        }

        initBodyCaller = false;
        this.updateSelected();
    };

    BootstrapTable.prototype.updateSelected = function () {
        if (!initBodyCaller) {
            _updateSelected.apply(this, Array.prototype.slice.apply(arguments));

            if ((this.options.groupBy) && (this.options.groupByField !== '')) {
                this.$selectGroup.forEach(function (item) {
                    var checkGroup = item.item.filter(':enabled').length ===
                        item.item.filter(':enabled').filter(':checked').length;

                    item.group.prop('checked', checkGroup);
                });
            }
        }
    };

    BootstrapTable.prototype.getGroupSelections = function (index) {
        var that = this;

        return $.grep(this.data, function (row) {
            return (row[that.header.stateField] && (row._data['parent-index'] === index));
        });
    };

    BootstrapTable.prototype.checkGroup = function (index) {
        this.checkGroup_(index, true);
    };

    BootstrapTable.prototype.uncheckGroup = function (index) {
        this.checkGroup_(index, false);
    };

    BootstrapTable.prototype.checkGroup_ = function (index, checked) {
        var rows;
        var filter = function() {
            return ($(this).closest('tr').data('parent-index') === index);
        };

        if (!checked) {
            rows = this.getGroupSelections(index);
        }

        this.$selectItem.filter(filter).prop('checked', checked);


        this.updateRows();
        this.updateSelected();
        if (checked) {
            rows = this.getGroupSelections(index);
        }
        this.trigger(checked ? 'check-all' : 'uncheck-all', rows);
    };

})(jQuery);